using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Collections.Generic;

namespace XZ.Logistics.WebShop
{
    public class Product : WebShopBase
    {
        private Guid _categoryId = Guid.Empty;
        public Guid CategoryId
        {
            get { return _categoryId; }
            set { _categoryId = value; }
        }

        private string _categoryTitle = "";
        public string CategoryTitle
        {
            get { return _categoryTitle; }
            private set { _categoryTitle = value; }
        }

        private Category _category = null;
        public Category Category
        {
            get
            {
                if (_category == null)
                    _category = Category.GetCategoryById(this.CategoryId);
                return _category;
            }
        }

        private string _title = "";
        public string Title
        {
            get { return _title; }
            set { _title = value; }
        }

        private string _description = null;
        public string Description
        {
            get
            {
                if (_description == null)
                    _description = WebShop.GetProductDescription(this.Id);
                return _description;
            }
            set { _description = value; }
        }

        private string _sku = "";
        public string SKU
        {
            get { return _sku; }
            set { _sku = value; }
        }

        private decimal _unitPrice = 0.0m;
        public decimal UnitPrice
        {
            get { return _unitPrice; }
            private set { _unitPrice = value; }
        }

        private int _discountPercentage = 0;
        public int DiscountPercentage
        {
            get { return _discountPercentage; }
            private set { _discountPercentage = value; }
        }

        public decimal FinalUnitPrice
        {
            get
            {
                if (this.DiscountPercentage > 0)
                    return this.UnitPrice - (this.UnitPrice * this.DiscountPercentage / 100);
                else
                    return this.UnitPrice;
            }
        }

        private int _unitsInStock = 0;
        public int UnitsInStock
        {
            get { return _unitsInStock; }
            private set { _unitsInStock = value; }
        }

        private string _smallImageUrl = "";
        public string SmallImageUrl
        {
            get { return _smallImageUrl; }
            set { _smallImageUrl = value; }
        }

        private string _fullImageUrl = "";
        public string FullImageUrl
        {
            get { return _fullImageUrl; }
            set { _fullImageUrl = value; }
        }

        private int _votes = 0;
        public int Votes
        {
            get { return _votes; }
            private set { _votes = value; }
        }

        private int _totalRating = 0;
        public int TotalRating
        {
            get { return _totalRating; }
            private set { _totalRating = value; }
        }

        public double AverageRating
        {
            get
            {
                if (this.Votes >= 1)
                    return ((double)this.TotalRating / (double)this.Votes);
                else
                    return 0.0;
            }
        }

        public Product(Guid id, DateTime addedDate, string addedBy,
           Guid categoryId, string categoryTitle, string title, string description,
           string sku, decimal unitPrice, int discountPercentage, int unitsInStock,
           string smallImageUrl, string fullImageUrl, int votes, int totalRating)
        {
            this.Id = id;
            this.AddedDate = addedDate;
            this.AddedBy = addedBy;
            this.CategoryId = categoryId;
            this.CategoryTitle = categoryTitle;
            this.Title = title;
            this.Description = description;
            this.SKU = sku;
            this.UnitPrice = unitPrice;
            this.DiscountPercentage = discountPercentage;
            this.UnitsInStock = unitsInStock;
            this.SmallImageUrl = smallImageUrl;
            this.FullImageUrl = fullImageUrl;
            this.Votes = votes;
            this.TotalRating = totalRating;
        }

        public bool Delete()
        {
            bool success = Product.DeleteProduct(this.Id);
            if (success)
                this.Id = Guid.Empty;
            return success;
        }

        public bool Update()
        {
            return Product.UpdateProduct(this.Id, this.CategoryId, this.Title,
               this.Description, this.SKU, this.UnitPrice, this.DiscountPercentage, this.UnitsInStock,
               this.SmallImageUrl, this.FullImageUrl);
        }

        public bool Rate(int rating)
        {
            return Product.RateProduct(this.Id, rating);
        }

        public bool DecrementUnitsInStock(int quantity)
        {
            bool success = Product.DecrementProductUnitsInStock(this.Id, quantity);
            if (success)
                this.UnitsInStock -= quantity;
            return success;
        }

        /***********************************
        * Static methods
        ************************************/

        /// <summary>
        /// Returns a collection with all products
        /// </summary>
        public static List<Product> GetProducts()
        {
            return GetProducts("", 0, BizObject.MAXROWS);
        }
        public static List<Product> GetProducts(string sortExpression, int startRowIndex, int maximumRows)
        {
            if (sortExpression == null)
                sortExpression = "";

            List<Product> products = null;
            string key = "WebShop_Products_" + sortExpression + "_" + startRowIndex.ToString() + "_" + maximumRows.ToString();

            if (WebShopBase.Settings.EnableCaching && BizObject.Cache[key] != null)
            {
                products = (List<Product>)BizObject.Cache[key];
            }
            else
            {
                products = WebShop.GetProducts(
                  sortExpression, GetPageIndex(startRowIndex, maximumRows), maximumRows);
                WebShopBase.CacheData(key, products);
            }
            return products;
        }

        /// <summary>
        /// Returns a collection with all products for the specified store department
        /// </summary>
        public static List<Product> GetProducts(Guid categoryId)
        {
            return GetProducts(categoryId, "", 0, BizObject.MAXROWS);
        }
        public static List<Product> GetProducts(Guid categoryId, string sortExpression, int startRowIndex, int maximumRows)
        {
            if (categoryId != Guid.Empty)
                return GetProducts(sortExpression, startRowIndex, maximumRows);

            List<Product> products = null;
            string key = "WebShop_Products_" + categoryId.ToString() + "_" + sortExpression + "_" +
               startRowIndex.ToString() + "_" + maximumRows.ToString();

            if (WebShopBase.Settings.EnableCaching && BizObject.Cache[key] != null)
            {
                products = (List<Product>)BizObject.Cache[key];
            }
            else
            {
                products = WebShop.GetProducts(categoryId,
                  sortExpression, GetPageIndex(startRowIndex, maximumRows), maximumRows);
                WebShopBase.CacheData(key, products);
            }
            return products;
        }

        /// <summary>
        /// Returns the number of total products
        /// </summary>
        public static int GetProductCount()
        {
            int productCount = 0;
            string key = "WebShop_ProductCount";

            if (WebShopBase.Settings.EnableCaching && BizObject.Cache[key] != null)
            {
                productCount = (int)BizObject.Cache[key];
            }
            else
            {
                productCount = WebShop.GetProductCount();
                WebShopBase.CacheData(key, productCount);
            }
            return productCount;
        }

        /// <summary>
        /// Returns the number of total products for the specified department
        /// </summary>      
        public static int GetProductCount(Guid categoryId)
        {
            if (categoryId != Guid.Empty)
                return GetProductCount();

            int productCount = 0;
            string key = "Store_ProductCount_" + categoryId.ToString();

            if (WebShopBase.Settings.EnableCaching && BizObject.Cache[key] != null)
            {
                productCount = (int)BizObject.Cache[key];
            }
            else
            {
                productCount = WebShop.GetProductCount(categoryId);
                WebShopBase.CacheData(key, productCount);
            }
            return productCount;
        }

        /// <summary>
        /// Returns an Product object with the specified ID
        /// </summary>
        public static Product GetProductById(Guid productId)
        {
            Product product = null;
            string key = "WebShop_Product_" + productId.ToString();

            if (WebShopBase.Settings.EnableCaching && BizObject.Cache[key] != null)
            {
                product = (Product)BizObject.Cache[key];
            }
            else
            {
                product = WebShop.GetProductById(productId);
                WebShopBase.CacheData(key, product);
            }
            return product;
        }

        /// <summary>
        /// Updates an existing product
        /// </summary>
        public static bool UpdateProduct(Guid id, Guid categoryId, string title,
           string description, string sku, decimal unitPrice, int discountPercentage,
           int unitsInStock, string smallImageUrl, string fullImageUrl)
        {
            title = BizObject.ConvertNullToEmptyString(title);
            description = BizObject.ConvertNullToEmptyString(description);
            sku = BizObject.ConvertNullToEmptyString(sku);
            smallImageUrl = BizObject.ConvertNullToEmptyString(smallImageUrl);
            fullImageUrl = BizObject.ConvertNullToEmptyString(fullImageUrl);

            Product record = new Product(id, DateTime.Now, "", categoryId,
               "", title, description, sku, unitPrice, discountPercentage, unitsInStock,
               smallImageUrl, fullImageUrl, 0, 0);
            bool ret = WebShop.UpdateProduct(record);

            BizObject.PurgeCacheItems("WebShop_Product_" + id.ToString());
            BizObject.PurgeCacheItems("WebShop_Products");
            return ret;
        }

        /// <summary>
        /// Creates a new product
        /// </summary>
        public static Guid InsertProduct(Guid categoryId, string title,
           string description, string sku, decimal unitPrice, int discountPercentage,
           int unitsInStock, string smallImageUrl, string fullImageUrl)
        {
            title = BizObject.ConvertNullToEmptyString(title);
            description = BizObject.ConvertNullToEmptyString(description);
            sku = BizObject.ConvertNullToEmptyString(sku);
            smallImageUrl = BizObject.ConvertNullToEmptyString(smallImageUrl);
            fullImageUrl = BizObject.ConvertNullToEmptyString(fullImageUrl);

            Product record = new Product(Guid.Empty, DateTime.Now, BizObject.CurrentUserName,
               categoryId, "", title, description, sku, unitPrice, discountPercentage,
               unitsInStock, smallImageUrl, fullImageUrl, 0, 0);
            Guid ret = WebShop.InsertProduct(record);

            BizObject.PurgeCacheItems("WebShop_Product");
            return ret;
        }

        /// <summary>
        /// Deletes an existing product
        /// </summary>
        public static bool DeleteProduct(Guid id)
        {
            bool ret = WebShop.DeleteProduct(id);
            //new RecordDeletedEvent("product", id, null).Raise();
            BizObject.PurgeCacheItems("WebShop_Product");
            return ret;
        }

        /// <summary>
        /// Increments a product's view count
        /// </summary>
        public static bool RateProduct(Guid id, int rating)
        {
            return WebShop.RateProduct(id, rating);
        }

        /// <summary>
        /// Decrements a product's UnitsInStock field
        /// </summary>
        public static bool DecrementProductUnitsInStock(Guid id, int quantity)
        {
            bool ret = WebShop.DecrementProductUnitsInStock(id, quantity);
            BizObject.PurgeCacheItems("WebShop_Product_" + id.ToString());
            return ret;
        }

    }
}